
/** 实现的三个重点：
 * 1. 支持异步调用resolve和reject
 * 2. 支持then、catch的异步调用
 * 3. then返回是一个Promise、需要循环处理下
 */
const PENDING = 'PENDING'
const FULLFILLED = 'FULLFILLED'
const  REJECTED = 'REJECTED'

function resovePromise(p, resolve, reject, x){
    if(x == p){
        throw new TypeError("Promise 不能返回自己")
    }
    // 判断x的类型
    if(x instanceof Promise){
        // then返回的是promise， 循环处理
         x.then((value)=>{
            resovePromise(p, resolve, reject, value)
        })
    }else{
        resolve(x)
    }
}

class MyPromise{

    // Promise接受一个函数作为参数，该函数称为构造器
    constructor(execute) {
       this.status = PENDING
       this.value = ''
       this.reason = ''
       this.onFullfilledArr = []
       this.onRejectedArr = []
       
       try {
            execute(this.reslove, this.reject)
       } catch (error) {
            this.reject(error)
       }

    } 

       
     reslove = (value) => {
        if(this.status == PENDING){
            this.status = FULLFILLED
            this.value = value
            // 执行回调函数数组
            this.onFullfilledArr.forEach((fn)=>{
                fn(this.value)
            })
        }
     }

    reject = (reason) => {
        if(this.status == PENDING){
            this.status = REJECTED
            this.reason = reason
            console.log(this.reason)
        }
    }

    // then接受的是回调函数
    then = (onFullfilled, onRejected) => {
        let p = new MyPromise((reslove, reject) => {
            if(this.status === REJECTED){
                queueMicrotask(()=>{
                    let x = onRejected(this.reason)
                    resovePromise(p,reslove, reject, x)
                })
            }else if(this.status === FULLFILLED){
                queueMicrotask(()=>{
                    let x = onFullfilled(this.value)
                    resovePromise(p,reslove, reject, x)
                })
            }else{
                // 向数组中传递一个回调函数
                // 使用回调函数处理异步问题
                    this.onFullfilledArr.push((value)=>{
                        let x = onFullfilled(value)
                        resovePromise(p,reslove, reject, x)
                    })
                    this.onRejectedArr.push((reason)=>{
                        let x =  onRejected(reason)
                        resovePromise(p,reslove, reject, x)
                    })
                }
            })
        return p
    }

    

}

new MyPromise((reslove, reject)=>{
    reslove(11)
}).then((value)=>{
    console.log('then', value)
    return new Promise((reslove, reject)=>{
        reslove(22)
    })
}).then((value)=>{
    console.log('then2',value)
})



new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve(1)
    },1000)
}).then((value)=>{
    console.log(value)
    return new Promise((reslove, reject)=>{
        reslove(2)
    })
}).then((value)=>{
    console.log(value)
})

